﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;

using System.IO;
namespace AutoTestEntry.Utility
{
    class ShellExecuter
    {
        private String type;
		private Process process;
		private StreamWriter consoleWriter;

		#region Self Defined Event
        public class ShellPrintEventArgs: EventArgs
        {
            public readonly String Data;
            public ShellPrintEventArgs(String data)
            {
                Data = data;
            }
        }

		public class ShellErrorEventArgs : EventArgs
		{
			public readonly String Data;
			public ShellErrorEventArgs(String data)
			{
				Data = data;
			}
		}

        public class ExecuteFinishedEventArgs : EventArgs
        {
            public readonly String Type;
			public readonly int ExitCode;
            public ExecuteFinishedEventArgs(String type, int exitCode)
            {
                Type = type;
				ExitCode = exitCode;
            }
        }

        //委托
        public delegate void ShellPrintEventHandler(Object sender, ShellPrintEventArgs e);
		public delegate void ShellErrorEventHandler(Object sender, ShellErrorEventArgs e);
        public delegate void ExecuteFinishedEventHandler(Object sender, ExecuteFinishedEventArgs e);

        //事件
        public event ShellPrintEventHandler ShellPrintEvent;
		public event ShellErrorEventHandler ShellErrorEvent;
        public event ExecuteFinishedEventHandler ExecuteFinishedEvent;
		#endregion

		#region Process Event Handler
		private void ProcessOutputDataReceiver(Object sender, DataReceivedEventArgs e)
		{
			if (!String.IsNullOrEmpty(e.Data))
			{
				ShellPrintEventArgs args = new ShellPrintEventArgs(e.Data);
				ShellPrintEvent(this, args);
			}
		}

		private void ProcessErrorDataReceiver(Object sender, DataReceivedEventArgs e)
		{
			if (!String.IsNullOrEmpty(e.Data))
			{
				ShellErrorEventArgs args = new ShellErrorEventArgs(e.Data);
				ShellErrorEvent(this, args);
			}
		}

		private void ProcessExitedHandler(Object sender, EventArgs e)
		{
			ExecuteFinishedEvent(this, new ExecuteFinishedEventArgs(type, process.ExitCode));
		}
		#endregion

		#region Real Work
		public void Run(String command, String args, String type)
        {
            this.type = type;
            process = new Process();
            process.StartInfo.FileName = command;
            process.StartInfo.Arguments = args;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
			process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardOutput = true;
			process.StartInfo.RedirectStandardError = true;
            process.EnableRaisingEvents = true;  // 设置进程结束时触发Exited事件

            process.Start();

			process.OutputDataReceived += ProcessOutputDataReceiver;
			process.ErrorDataReceived += ProcessErrorDataReceiver;
			process.Exited += ProcessExitedHandler;
			consoleWriter = process.StandardInput;

            process.BeginOutputReadLine();
			process.BeginErrorReadLine();
            
        }
		public void Kill()
		{
			try
			{
				process.Kill();
			}
			catch
			{
			}
		}
		public void WriteCommand(String cmd)
		{
			consoleWriter.WriteLine(cmd);
		}
		#endregion
	}
}
